/**
 * 
 */
package it.polimi.cg16.client.gui;

import static it.polimi.cg16.client.gui.GUIConstants.CELL_COORDINATES;
import static it.polimi.cg16.client.gui.GUIConstants.CELL_LABEL_DIMENSION;
import static it.polimi.cg16.client.gui.GUIConstants.NUMBER_OF_CELLS;
import static it.polimi.cg16.client.gui.GUIConstants.NUMBER_OF_REGIONS;
import static it.polimi.cg16.client.gui.GUIConstants.REGIONS_BLACKSHEEP_COORDINATES;
import static it.polimi.cg16.client.gui.GUIConstants.REGIONS_COORDINATES;
import static it.polimi.cg16.client.gui.GUIConstants.REGIONS_WOLF_COORDINATES;
import static it.polimi.cg16.client.gui.GUIConstants.REGION_LABEL_DIMENSION_X;
import static it.polimi.cg16.client.gui.GUIConstants.REGION_LABEL_DIMENSION_Y;
import static it.polimi.cg16.model.Terrain.COUNTRY;
import static it.polimi.cg16.model.Terrain.DESERT;
import static it.polimi.cg16.model.Terrain.MOUNTAIN;
import static it.polimi.cg16.model.Terrain.PLAIN;
import static it.polimi.cg16.model.Terrain.SWAMP;
import static it.polimi.cg16.model.Terrain.WOOD;
import it.polimi.cg16.client.Card;
import it.polimi.cg16.client.CellClient;
import it.polimi.cg16.client.GameBoardClient;
import it.polimi.cg16.client.MoveClient;
import it.polimi.cg16.client.MyActionListener;
import it.polimi.cg16.client.PlayerClient;
import it.polimi.cg16.model.Region;
import it.polimi.cg16.model.Terrain;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;

/**
 * @author Andrea & Michele
 * 
 */
public class GameBoardGUI {
    private static final int SPEED = 1000;
    // Constants
    static final int SHEEPSBURG = 0;
    static final int CARD_PER_TERRAIN = 5;
    static final int STARTER_CARD_FOREACH = 1;
    static final int WIDTH_DIMENSION = 800;
    static final int HEIGHT_DIMENSION = 600;

    // Game components
    private GameBoardClient gameBoard;
    private MyActionListener actionListener;
    private PlayerClient player;

    // GUI components
    private JFrame mainFrame;
    private JPanel mainPanel;
    private JPanel cardsPanel;
    private JPanel shepherdsPanel;
    private JPanel movesPanel;
    private JPanel centerPanel;
    private JPanel mapPanel;
    private JPanel toolsPanel;
    private JPanel myPlainCardPanel;
    private JPanel myWoodCardPanel;
    private JPanel mySwampCardPanel;
    private JPanel myMountainCardPanel;
    private JPanel myDesertCardPanel;
    private JPanel myCountryCardPanel;
    private JLabel backLabel;
    private JLabel moneyLabel;
    private JLabel infoLabel;
    private JLabel plainLabel;
    private JLabel woodLabel;
    private JLabel swampLabel;
    private JLabel mountainLabel;
    private JLabel desertLabel;
    private JLabel countryLabel;
    private ImageIcon mapBackground;
    private ImageIcon mapBackgroundResized;

    private List<CardButton> cardButtons;
    private CardButton plainButton;
    private CardButton woodButton;
    private CardButton swampButton;
    private CardButton mountainButton;
    private CardButton desertButton;
    private CardButton countryButton;

    private Dimension stdDimension;

    private List<MoveLabel> moveLabels;
    private ShepherdIcon[] myShepherdIcons;
    private ShepherdIcon[] otherShepherdIcons;
    private CellLabel[] cellLabels;
    private SheepIcon[] sheepIcons;
    private BlackSheepIcon blackSheepIcon;
    private WolfIcon wolfIcon;

    public GameBoardGUI(GameBoardClient gameBoard, MyActionListener actionListener, PlayerClient player) {
        this.gameBoard = gameBoard;
        this.actionListener = actionListener;
        this.player = player;
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                initGraphic();
            }
        });
    }

    // ------------------------------------------------------------------------------------------
    // GRAPHICAL METHODS
    // ------------------------------------------------------------------------------------------

    /**
     * This method draw the starter frame and its components
     */
    public void drawFrame() {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                // Setting components
                setComponents();

                // Adding components
                addComponents();

                // Adding listener
                addActionListener();

                mainFrame.pack();

                mainFrame.setVisible(true);
            }
        });

    }

    /**
     * This method is called each time by the ClientController class to update
     * the game's frame
     */
    public void updateFrame() {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                // Refreshing the deck view
                plainButton.setCard(getFirstCard(PLAIN));
                woodButton.setCard(getFirstCard(WOOD));
                swampButton.setCard(getFirstCard(SWAMP));
                mountainButton.setCard(getFirstCard(MOUNTAIN));
                desertButton.setCard(getFirstCard(DESERT));
                countryButton.setCard(getFirstCard(COUNTRY));

                // Refreshing card owned labels
                plainLabel.setText(Integer.toString(getNumberOfCard(PLAIN)));
                woodLabel.setText(Integer.toString(getNumberOfCard(WOOD)));
                swampLabel.setText(Integer.toString(getNumberOfCard(SWAMP)));
                mountainLabel.setText(Integer.toString(getNumberOfCard(MOUNTAIN)));
                desertLabel.setText(Integer.toString(getNumberOfCard(DESERT)));
                countryLabel.setText(Integer.toString(getNumberOfCard(COUNTRY)));

                // Refreshing number of sheep in each region
                for (int i = 0; i < sheepIcons.length; i++) {
                    sheepIcons[i].updateNumberOfSheep();
                }

                // Refreshing blacksheep icon position performing a movement
                if (blackSheepIcon.isKilled()) {
                    blackSheepIcon.setVisible(false);
                } else {
                    blackSheepIcon.moveTo(REGIONS_BLACKSHEEP_COORDINATES[gameBoard.getBlackSheepIdRegion()], SPEED);
                }

                // Refreshing wolf icon position performing movement
                wolfIcon.moveTo(REGIONS_WOLF_COORDINATES[gameBoard.getWolfIdRegion()], SPEED);

                // Refreshing cell label
                for (CellLabel label : cellLabels) {
                    label.update();
                }

                // Refreshing shepherd's icons, only if shepherds are been
                // initialized
                if (gameBoard.getOtherShepherds().size() != 0) {
                    for (int i = 0; i < myShepherdIcons.length; i++) {
                        myShepherdIcons[i].moveTo(CELL_COORDINATES[myShepherdIcons[i].getCell()], SPEED);
                    }
                    for (int i = 0; i < otherShepherdIcons.length; i++) {
                        otherShepherdIcons[i].moveTo(CELL_COORDINATES[otherShepherdIcons[i].getCell()], SPEED);
                    }
                }
            }
        });

    }

    /**
     * Initialize all graphic objects
     */
    private void initGraphic() {

        // Initializing components
        stdDimension = new Dimension(WIDTH_DIMENSION, HEIGHT_DIMENSION);

        mainFrame = new JFrame("Sheepland!");
        mainPanel = new JPanel();
        centerPanel = new JPanel();
        mapPanel = new JPanel();
        cardsPanel = new JPanel(new GridLayout(6, 1));
        shepherdsPanel = new JPanel(new GridLayout(6, 1));
        movesPanel = new JPanel();
        toolsPanel = new JPanel();
        myPlainCardPanel = new JPanel();
        myWoodCardPanel = new JPanel();
        mySwampCardPanel = new JPanel();
        myMountainCardPanel = new JPanel();
        myDesertCardPanel = new JPanel();
        myCountryCardPanel = new JPanel();
        moneyLabel = new JLabel();
        infoLabel = new JLabel();

        mapBackground = new ImageIcon("images\\GameBoardImg.jpg");
        mapBackgroundResized = resizeImage(mapBackground.getImage(), stdDimension);

        backLabel = new JLabel(mapBackgroundResized);
        cellLabels = new CellLabel[NUMBER_OF_CELLS];
        sheepIcons = new SheepIcon[NUMBER_OF_REGIONS];

        cardButtons = new ArrayList<>();
        plainButton = new CardButton();
        woodButton = new CardButton();
        swampButton = new CardButton();
        mountainButton = new CardButton();
        desertButton = new CardButton();
        countryButton = new CardButton();
        cardButtons.add(plainButton);
        cardButtons.add(woodButton);
        cardButtons.add(swampButton);
        cardButtons.add(mountainButton);
        cardButtons.add(desertButton);
        cardButtons.add(countryButton);

        plainLabel = new JLabel();
        woodLabel = new JLabel();
        swampLabel = new JLabel();
        mountainLabel = new JLabel();
        desertLabel = new JLabel();
        countryLabel = new JLabel();

        moveLabels = new ArrayList<>();
        for (MoveClient move : MoveClient.values()) {
            moveLabels.add(new MoveLabel(move));
        }
        for (int i = 0; i < cellLabels.length; i++) {
            cellLabels[i] = new CellLabel(gameBoard.getCells()[i]);
        }
        for (int i = 0; i < sheepIcons.length; i++) {
            sheepIcons[i] = new SheepIcon(gameBoard.getRegions()[i]);
        }
        blackSheepIcon = new BlackSheepIcon(gameBoard.getBlackSheep());
        wolfIcon = new WolfIcon();

    }

    /**
     * Set all the components of the GUI
     */
    private void setComponents() {
        mainFrame.setSize(stdDimension);
        mainFrame.setLocationRelativeTo(null);
        mainFrame.setResizable(false);
        mainFrame.setContentPane(backLabel);
        mainFrame.setLayout(new BorderLayout());
        mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        mainPanel.setOpaque(false);
        mainPanel.setLayout(new BorderLayout());
        centerPanel.setLayout(new BorderLayout());
        centerPanel.setOpaque(false);
        movesPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
        movesPanel.setOpaque(false);
        cardsPanel.setOpaque(false);
        shepherdsPanel.setOpaque(false);
        mapPanel.setLayout(null);
        mapPanel.setOpaque(false);
        myPlainCardPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
        myPlainCardPanel.setOpaque(false);
        myWoodCardPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
        myWoodCardPanel.setOpaque(false);
        mySwampCardPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
        mySwampCardPanel.setOpaque(false);
        myMountainCardPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
        myMountainCardPanel.setOpaque(false);
        myDesertCardPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
        myDesertCardPanel.setOpaque(false);
        myCountryCardPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
        myCountryCardPanel.setOpaque(false);
        plainButton.setCard(getFirstCard(PLAIN));
        woodButton.setCard(getFirstCard(WOOD));
        swampButton.setCard(getFirstCard(SWAMP));
        mountainButton.setCard(getFirstCard(MOUNTAIN));
        desertButton.setCard(getFirstCard(DESERT));
        countryButton.setCard(getFirstCard(COUNTRY));
        for (CardButton card : cardButtons) {
            card.setLayout(new BorderLayout());
        }
        wolfIcon.setLocation(new Point(REGIONS_WOLF_COORDINATES[SHEEPSBURG]));
        wolfIcon.setSize(REGION_LABEL_DIMENSION_Y, REGION_LABEL_DIMENSION_X);
        plainLabel.setForeground(Color.RED);
        plainLabel.setFont(new Font("Serif", Font.BOLD, 18));
        plainLabel.setText("0");
        woodLabel.setForeground(Color.RED);
        woodLabel.setFont(new Font("Serif", Font.BOLD, 18));
        woodLabel.setText("0");
        swampLabel.setForeground(Color.RED);
        swampLabel.setFont(new Font("Serif", Font.BOLD, 18));
        swampLabel.setText("0");
        mountainLabel.setForeground(Color.RED);
        mountainLabel.setFont(new Font("Serif", Font.BOLD, 18));
        mountainLabel.setText("0");
        desertLabel.setForeground(Color.RED);
        desertLabel.setFont(new Font("Serif", Font.BOLD, 18));
        desertLabel.setText("0");
        countryLabel.setForeground(Color.RED);
        countryLabel.setFont(new Font("Serif", Font.BOLD, 18));
        countryLabel.setText("0");
        moneyLabel.setForeground(Color.WHITE);
        moneyLabel.setText("Money:");
        infoLabel.setForeground(Color.WHITE);
        infoLabel.setText("Wait for your tourn!");
        toolsPanel.setOpaque(false);
        toolsPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
    }

    /**
     * Add all components to the mainFrame and its panels
     */
    private void addComponents() {
        plainButton.add(myPlainCardPanel, BorderLayout.SOUTH);
        myPlainCardPanel.add(plainLabel);
        woodButton.add(myWoodCardPanel, BorderLayout.SOUTH);
        myWoodCardPanel.add(woodLabel);
        swampButton.add(mySwampCardPanel, BorderLayout.SOUTH);
        mySwampCardPanel.add(swampLabel);
        mountainButton.add(myMountainCardPanel, BorderLayout.SOUTH);
        myMountainCardPanel.add(mountainLabel);
        desertButton.add(myDesertCardPanel, BorderLayout.SOUTH);
        myDesertCardPanel.add(desertLabel);
        countryButton.add(myCountryCardPanel, BorderLayout.SOUTH);
        myCountryCardPanel.add(countryLabel);

        cardsPanel.add(plainButton);
        cardsPanel.add(woodButton);
        cardsPanel.add(swampButton);
        cardsPanel.add(mountainButton);
        cardsPanel.add(desertButton);
        cardsPanel.add(countryButton);

        for (MoveLabel button : moveLabels) {
            movesPanel.add(button);
        }
        toolsPanel.add(moneyLabel);
        toolsPanel.add(infoLabel);
        addCellLabels();
        addSheepIcons();
        mapPanel.add(wolfIcon);
        centerPanel.add(toolsPanel, BorderLayout.NORTH);
        centerPanel.add(mapPanel, BorderLayout.CENTER);
        centerPanel.add(movesPanel, BorderLayout.SOUTH);
        mainPanel.add(centerPanel, BorderLayout.CENTER);
        mainPanel.add(cardsPanel, BorderLayout.WEST);
        mainPanel.add(shepherdsPanel, BorderLayout.EAST);
        mainFrame.add(mainPanel, BorderLayout.CENTER);

    }

    /**
     * Add listeners to each label/buttons
     */
    private void addActionListener() {
        // Add MouseListener to cell
        for (CellLabel label : cellLabels) {
            label.addMouseListener(actionListener);
        }
        // Add MouseListener to move buttons
        for (MoveLabel label : moveLabels) {
            label.addMouseListener(actionListener);
        }
        // Add ActionListener to card buttons
        for (CardButton card : cardButtons) {
            card.addActionListener(actionListener);
        }
        // Add MouseListener to sheep icons
        for (SheepIcon icon : sheepIcons) {
            icon.addMouseListener(actionListener);
        }

        blackSheepIcon.addMouseListener(actionListener);

        mainFrame.addWindowListener(new WindowListener() {

            @Override
            public void windowOpened(WindowEvent arg0) {
                // not implemented
            }

            @Override
            public void windowIconified(WindowEvent arg0) {
                // not implemented
            }

            @Override
            public void windowDeiconified(WindowEvent arg0) {
                // not implemented
            }

            @Override
            public void windowDeactivated(WindowEvent arg0) {
                // not implemented
            }

            @Override
            public void windowClosing(WindowEvent arg0) {
                actionListener.closingClient();
            }

            @Override
            public void windowClosed(WindowEvent arg0) {
                // not implemented
            }

            @Override
            public void windowActivated(WindowEvent arg0) {
                // not implemented
            }
        });
    }

    /**
     * Add cell buttons to the map
     */
    private void addCellLabels() {

        for (int i = 0; i < cellLabels.length; i++) {
            mapPanel.add(cellLabels[i]);
            cellLabels[i].setSize(CELL_LABEL_DIMENSION, CELL_LABEL_DIMENSION);
            cellLabels[i].setLocation(new Point(CELL_COORDINATES[i]));
        }
    }

    /**
     * Add Sheep icons to the map in each region
     */
    private void addSheepIcons() {
        mapPanel.add(blackSheepIcon);
        blackSheepIcon.setLocation(new Point(REGIONS_BLACKSHEEP_COORDINATES[SHEEPSBURG]));
        for (int i = 0; i < sheepIcons.length; i++) {
            mapPanel.add(sheepIcons[i]);
            sheepIcons[i].setSize(REGION_LABEL_DIMENSION_X, REGION_LABEL_DIMENSION_Y);
            sheepIcons[i].setLocation(new Point(REGIONS_COORDINATES[i]));
        }
    }

    /**
     * Add shepherd's icons to the map. It works only after icons initialization
     */
    private void addShepherds() {
        for (int i = 0; i < myShepherdIcons.length; i++) {
            mapPanel.add(myShepherdIcons[i]);
            myShepherdIcons[i].setLocation(new Point(CELL_COORDINATES[myShepherdIcons[i].getCell()]));
        }
        for (int i = 0; i < otherShepherdIcons.length; i++) {
            mapPanel.add(otherShepherdIcons[i]);
            otherShepherdIcons[i].setLocation(new Point(CELL_COORDINATES[otherShepherdIcons[i].getCell()]));
        }

    }

    /**
     * Set the text of the money label for this player
     * 
     * @param money
     *            of the player
     */
    public void setMoneyLabel(Integer money) {
        moneyLabel.setText("Money: " + money.toString());
    }

    /**
     * Set the text of the information label for this player
     * 
     * @param a
     *            string with the message to be displayed
     */
    public void setInfoLabel(String info) {
        infoLabel.setText(player.getUsername() + ": " + info);
    }

    /**
     * Disables the move labels
     */
    public void resetMoves() {

        for (MoveLabel moveLabel : moveLabels) {
            moveLabel.setEnabled(false);
        }

    }

    /**
     * Disables the cell labels
     */
    public void resetCells() {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                for (CellLabel cell : cellLabels) {
                    cell.setEnabled(false);
                    if (cell.isTransparent()) {
                        cell.setVisible(false);
                    } else if (cell.isLocked()) {
                        cell.setVisible(true);
                    }
                }
            }
        });
    }

    /**
     * Disables the shepherd icons
     */
    public void resetShepherds() {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                if (myShepherdIcons != null) {
                    for (ShepherdIcon icon : myShepherdIcons) {
                        icon.setEnabled(false);
                    }
                }
            }
        });
    }

    /**
     * Disables the card buttons
     */
    public void resetCards() {
        for (CardButton card : cardButtons) {
            card.setEnabled(false);
        }
    }

    /**
     * Disables sheep buttons
     */
    public void resetSheep() {
        for (SheepIcon icon : sheepIcons) {
            icon.setSelectable(false);
        }
        blackSheepIcon.setEnabled(false);
    }

    /**
     * Disables all buttons
     */
    public void resetAll() {
        resetMoves();
        resetCells();
        resetShepherds();
        resetCards();
        resetSheep();
    }

    /**
     * Enables a specific move button
     * 
     * @param the
     *            move to be enable
     */
    public void enableMoves(MoveClient move) {
        for (MoveLabel moveButton : moveLabels) {
            if (move.equals(moveButton.getMove())) {
                moveButton.setEnabled(true);
                if (move.equals(MoveClient.SHEPHERD)) {
                    moveButton.setShepherdColor(player.getShepherds().get(player.getChosenShepherd()).getColor());
                }
            }
        }
    }

    /**
     * Enables a specific sheep label in a given region
     * 
     * @param region
     *            in which enable the sheep label
     */
    public void enableSheep(Region region) {
        for (SheepIcon icon : sheepIcons) {
            if (icon.getRegion().equals(region) && region.getSheep().size() > 0 && !hasOnlyBlackSheep(region)) {
                icon.setSelectable(true);
            }
        }
        if (gameBoard.getBlackSheepIdRegion() == region.getId()) {
            blackSheepIcon.setEnabled(true);
        }
    }

    /**
     * 
     * @param region
     *            to verify
     * @return true if a region contains only a blackSheep, false otherwise
     */
    private boolean hasOnlyBlackSheep(Region region) {
        if (region.getId() == gameBoard.getBlackSheepIdRegion() && region.getSheep().size() == 1) {
            return true;
        }
        return false;
    }

    /**
     * Enables all free cells
     */
    public void enableCells() {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                for (int i = 0; i < NUMBER_OF_CELLS; i++) {
                    if (gameBoard.getCells()[i].getState() == CellClient.FREE) {
                        cellLabels[i].setEnabled(true);
                        cellLabels[i].setVisible(true);
                    }
                }
            }
        });
    }

    /**
     * Enables only my shepherd icons
     */
    public void enableMyShepherd() {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                for (ShepherdIcon icon : myShepherdIcons) {
                    icon.setEnabled(true);
                }
            }
        });
    }

    /**
     * Enables specific terrain card to buy
     * 
     * @param terrain
     *            type
     */
    public void enableCards(Terrain terrain) {
        for (CardButton card : cardButtons) {
            if (terrain.equals(card.getTerrain())) {
                card.setEnabled(true);
            }
        }
    }

    /**
     * Initializes the Shepherd icons. it's be invoked by ClientController
     */
    public void initShepherds() {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                myShepherdIcons = new ShepherdIcon[player.getShepherds().size()];
                for (int i = 0; i < myShepherdIcons.length; i++) {
                    myShepherdIcons[i] = new ShepherdIcon(player.getShepherds().get(i));
                    myShepherdIcons[i].addMouseListener(actionListener);
                }
                otherShepherdIcons = new ShepherdIcon[gameBoard.getOtherShepherds().size()];
                for (int i = 0; i < otherShepherdIcons.length; i++) {
                    otherShepherdIcons[i] = new ShepherdIcon(gameBoard.getOtherShepherds().get(i));
                }
                addShepherds();
            }
        });
    }

    /**
     * Show a tabled label with the points of all players
     * 
     * @param otherPlayers
     * @param sheepsPerTerrain
     */
    public void showResults(List<PlayerClient> otherPlayers, Map<Terrain, Integer> sheepsPerTerrain) {
        mainPanel.removeAll();

        mapBackground = new ImageIcon("images\\GameBoardImgGrey.jpg");
        mapBackgroundResized = resizeImage(mapBackground.getImage(), stdDimension);
        backLabel.setIcon(mapBackgroundResized);

        JPanel resultPanel = new JPanel(new GridBagLayout());
        JPanel winPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
        GridBagConstraints c = new GridBagConstraints();
        c.ipadx = 5;
        c.ipady = 30;
        resultPanel.setOpaque(false);

        JLabel[] playerLabels = new JLabel[1 + otherPlayers.size()];

        ImageIcon playerIcon = new ImageIcon("images\\player" + player.getShepherds().get(0).getColor().getName() + ".png");
        playerLabels[0] = new JLabel(playerIcon);
        playerLabels[0].setLayout(new BorderLayout());
        JLabel userLabel = new JLabel(player.getUsername(), SwingConstants.CENTER);
        userLabel.setForeground(Color.WHITE);
        playerLabels[0].add(userLabel, BorderLayout.SOUTH);
        c.gridx = 0;
        c.gridy = 1;
        resultPanel.add(playerLabels[0], c);
        for (int i = 1; i <= otherPlayers.size(); i++) {
            playerLabels[i] = new JLabel(new ImageIcon("images\\player" + otherPlayers.get(i - 1).getColor().getName() + ".png"));
            playerLabels[i].setLayout(new BorderLayout());
            userLabel = new JLabel(otherPlayers.get(i - 1).getUsername(), SwingConstants.CENTER);
            userLabel.setForeground(Color.WHITE);
            playerLabels[i].add(userLabel, BorderLayout.SOUTH);
            c.gridx = 0;
            c.gridy = i + 1;
            resultPanel.add(playerLabels[i], c);
        }

        JLabel[] terrainLabels = new JLabel[6];
        for (int i = 0; i < terrainLabels.length; i++) {
            terrainLabels[i] = new JLabel(new ImageIcon("images\\" + Terrain.values()[i].getTypeName() + "0.png"));
            c.gridx = i + 1;
            c.gridy = 0;
            resultPanel.add(terrainLabels[i], c);
        }

        JLabel resultMoneyLabel = new JLabel(new ImageIcon("images\\manyMoney.png"));
        c.gridx = 7;
        c.gridy = 0;
        resultPanel.add(resultMoneyLabel, c);

        JLabel totalLabel = new JLabel(new ImageIcon("images\\tot.png"));
        c.gridx = 8;
        c.gridy = 0;
        resultPanel.add(totalLabel, c);

        // Set pointLabels position
        JLabel[][] pointLabels = new JLabel[4][8];
        for (int j = 0; j < otherPlayers.size() + 1; j++) {
            for (int i = 0; i < 8; i++) {
                pointLabels[j][i] = new JLabel();
                pointLabels[j][i].setFont(new Font("Serif", Font.BOLD, 30));
                pointLabels[j][i].setForeground(Color.BLUE);
                c.gridx = (i + 1);
                c.gridy = (j + 1);
                resultPanel.add(pointLabels[j][i], c);
            }
        }

        // Show points

        setPoints(sheepsPerTerrain, pointLabels, otherPlayers, winPanel);

        mainPanel.add(winPanel, BorderLayout.NORTH);
        mainPanel.add(resultPanel, BorderLayout.CENTER);
        mainPanel.revalidate();
        mainPanel.repaint();

    }

    /**
     * Set each label with the correct point
     * 
     * @param sheepsPerTerrain
     *            parameter passed to showResult by the controller
     * @param pointLabels
     *            the list of labels to set
     * @param otherPlayers
     *            parameter passed to showResult by the controller
     * @param winPanel
     *            the panel in which write the winning status
     */
    private void setPoints(Map<Terrain, Integer> sheepsPerTerrain, JLabel[][] pointLabels, List<PlayerClient> otherPlayers, JPanel winPanel) {
        int tot = 0;
        int totplayer = 0;
        boolean win = true;
        for (Terrain t : Terrain.values()) {
            int num = 0;
            for (Card card : player.getTerrainCards()) {
                if (card.getTerrain() == t) {
                    num++;
                }
            }
            tot = tot + num * sheepsPerTerrain.get(t);
            pointLabels[0][t.getTypeConstant()].setText(Integer.toString(tot));
        }
        pointLabels[0][6].setText(Integer.toString(player.getMoney()));
        tot = tot + player.getMoney();
        pointLabels[0][7].setText(Integer.toString(tot));
        totplayer = tot;

        for (int j = 0; j < otherPlayers.size(); j++) {
            tot = 0;
            for (Terrain t : Terrain.values()) {
                int num = 0;
                for (Card card : otherPlayers.get(j).getTerrainCards()) {
                    if (card.getTerrain() == t) {
                        num = card.getCost();
                    }
                }
                tot = tot + num * sheepsPerTerrain.get(t);
                pointLabels[j + 1][t.getTypeConstant()].setText(Integer.toString(tot));
            }
            pointLabels[j + 1][6].setText(Integer.toString(otherPlayers.get(j).getMoney()));
            tot = tot + otherPlayers.get(j).getMoney();
            pointLabels[j + 1][7].setText(Integer.toString(tot));
            if (tot > totplayer) {
                win = false;
            }
        }

        if (win) {
            JLabel winner = new JLabel("Hai Vinto!");
            winner.setFont(new Font("Serif", Font.BOLD, 60));
            winner.setForeground(Color.BLUE);

            winPanel.add(winner);
            winPanel.setOpaque(false);

        } else {
            JLabel loser = new JLabel("Hai Perso!");
            loser.setFont(new Font("Serif", Font.BOLD, 60));
            loser.setForeground(Color.BLUE);
            winPanel.add(loser);
            winPanel.setOpaque(false);

        }
    }

    // ------------------------------------------------------------------------------------------
    // DATA METHODS
    // ------------------------------------------------------------------------------------------

    /**
     * Get the less expensive card left in the deck of given terrain
     * 
     * @param terrain
     * @return
     */
    private Card getFirstCard(Terrain terrain) {
        for (Card card : gameBoard.getDeckClient()) {
            if (card.getTerrain().equals(terrain)) {
                return card;
            }
        }
        return new Card(terrain, -1);
    }

    /**
     * 
     * @param terrain
     *            type
     * @return the number of card of the specified terrain the player owns
     */
    private int getNumberOfCard(Terrain terrain) {
        int number = 0;
        for (Card card : player.getTerrainCards()) {
            if (terrain.equals(card.getTerrain())) {
                number++;
            }
        }
        return number;
    }

    /**
     * Resize the image given with the specified dimension
     * 
     * @param the
     *            image to be resized
     * @return a resized image
     */
    private ImageIcon resizeImage(Image img, Dimension dim) {
        Image resizedImg = img.getScaledInstance(dim.width, dim.height, Image.SCALE_SMOOTH);
        return new ImageIcon(resizedImg);
    }

}
